/*
 * Copyright (c) Huawei Technologies Co., Ltd. 2024. All rights reserved.
 */

#include "CommandPool.h"
#include "log.hpp"

namespace OHTestApp {
namespace {
// 静态标志，用于控制高频操作的日志输出
static bool s_loggedAllocateCommandBuffers = false;
static bool s_loggedFreeCommandBuffers = false;
} // end of anonymous namespace

bool CommandPool::Init(const CommandPoolDescriptor &descriptor)
{
    m_descriptor = descriptor;
    m_device = descriptor.device;
    m_queue = descriptor.queue;

    VkCommandPoolCreateInfo poolInfo{};
    poolInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
    poolInfo.flags = descriptor.flags;
    poolInfo.queueFamilyIndex = descriptor.queueFamilyIndex;

    VkResult result = vkCreateCommandPool(m_device, &poolInfo, nullptr, &m_commandPool);
    if (result == VK_SUCCESS) {
        GOLOGW("vkCreateCommandPool completed successfully for %s", m_descriptor.name.c_str());
        return true;
    } else {
        GOLOGE("vkCreateCommandPool failed with error: %d for %s", result, m_descriptor.name.c_str());
        return false;
    }
}

void CommandPool::Destroy()
{
    if (m_commandPool != VK_NULL_HANDLE) {
        GOLOGD("Destroying command pool %s", m_descriptor.name.c_str());
        vkDestroyCommandPool(m_device, m_commandPool, nullptr);
        GOLOGW("vkDestroyCommandPool completed successfully");
        m_commandPool = VK_NULL_HANDLE;
    }
}

CommandPool::~CommandPool()
{
    Destroy();
}

VkCommandBuffer CommandPool::AllocateSingleTimeCommandBuffer()
{
    VkCommandBufferAllocateInfo allocInfo{};
    allocInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
    allocInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
    allocInfo.commandPool = m_commandPool;
    allocInfo.commandBufferCount = 1;

    VkCommandBuffer commandBuffer = VK_NULL_HANDLE;
    VkResult result = vkAllocateCommandBuffers(m_device, &allocInfo, &commandBuffer);
    if (result == VK_SUCCESS) {
        if (!s_loggedAllocateCommandBuffers) {
            GOLOGW("vkAllocateCommandBuffers completed successfully");
            s_loggedAllocateCommandBuffers = true;
        }
    } else {
        GOLOGE("vkAllocateCommandBuffers failed with error: %d", result);
    }
    return commandBuffer;
}

void CommandPool::DeallocateSingleTimeCommandBuffer(VkCommandBuffer commandBuffer)
{
    vkFreeCommandBuffers(m_device, m_commandPool, 1, &commandBuffer);
    if (!s_loggedFreeCommandBuffers) {
        GOLOGW("vkFreeCommandBuffers completed successfully");
        s_loggedFreeCommandBuffers = true;
    }
}

VkQueue CommandPool::GetQueue()
{
    return m_queue;
}

uint32_t CommandPool::GetQueueIndex()
{
    return m_descriptor.queueFamilyIndex;
}

void CommandPool::AllocateCommandBuffers(VkCommandBuffer *cmdBuffers, uint32_t num)
{
    VkCommandBufferAllocateInfo allocInfo{};
    allocInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
    allocInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
    allocInfo.commandPool = m_commandPool;
    allocInfo.commandBufferCount = num;

    VkResult result = vkAllocateCommandBuffers(m_device, &allocInfo, cmdBuffers);
    if (result == VK_SUCCESS) {
        if (!s_loggedAllocateCommandBuffers) {
            GOLOGW("vkAllocateCommandBuffers completed successfully");
            s_loggedAllocateCommandBuffers = true;
        }
    } else {
        GOLOGE("vkAllocateCommandBuffers failed with error: %d", result);
    }
}

void CommandPool::DeaocateCommandBuffers(VkCommandBuffer *cmdBuffers, uint32_t num)
{
    vkFreeCommandBuffers(m_device, m_commandPool, num, cmdBuffers);
    if (!s_loggedFreeCommandBuffers) {
        GOLOGW("vkFreeCommandBuffers completed successfully");
        s_loggedFreeCommandBuffers = true;
    }
}
} // namespace OHTestApp
